package graph.parts;

import static org.lwjgl.opengl.GL20.glUseProgram;
import graph.Main;
import graph.Part;

import java.util.LinkedList;
import java.util.List;

import org.lwjgl.opengl.GL11;

import ogl.vecmathimp.MatrixImp;
import shader.Shader;

public class Group extends Part {
	protected List<Part> parts;
	protected MatrixImp matrix;
	private Shader shader;

	/**
	 * Gruppenknoten. Benutzt zum Zeichnen seiner Kinder die defaultShader der
	 * laufenden Szene als Shader.
	 */
	public Group() {
		parts = new LinkedList<Part>();
		matrix = (MatrixImp) MatrixImp.identity;
	}

	@Override
	public MatrixImp getMatrix() {
		return matrix;
	}

	@Override
	public void setMatrix(MatrixImp m) {
		matrix = m;
	}

	public void addPart(Part p) {
		parts.add(p);
	}

	public void removePart(Part p) {
		if (parts.contains(p)) {
			parts.remove(p);
		} else
			for (Part part : parts) {
				if (part instanceof Group) {
					((Group) part).removePart(p);
				}
			}
	}

	public boolean contains(Part p) {
		if (parts.contains(p)) {
			return true;
		}
		for (Part part : parts) {
			if (part instanceof Group) {
				return ((Group) part).contains(p);
			}
		}
		return false;
	}

	@Override
	public void draw(MatrixImp m) {
		childrenUseShader(shader);
		MatrixImp m2 = (MatrixImp) matrix.mult(m);
		for (Part p : parts) {
			p.draw(m2);
		}
	}

	protected void childrenUseShader(Shader s) {
		for (Part p : parts) {
			if (p instanceof Shape)
				((Shape) p).setShader(s);
			if (p instanceof Group) 
				((Group) p).setShader(s);
		}
	}
	
	protected void setShader(Shader s) {
		shader = s;
	}

	@Override
	public MatrixImp findCamera() {
		for (Part p : parts) {
			MatrixImp m = p.findCamera();
			if (m != null) {
				return (MatrixImp) matrix.invertFull().mult(m);
			}
		}
		return null;
	}

	@Override
	public MatrixImp findLight() {
		for (Part p : parts) {
			MatrixImp m = p.findLight();
			if (m != null) {
				// nicht setMatrix! Sonst wird immer aufaddiert
				return (MatrixImp) matrix.mult(m);
			}
		}
		return null;
	}
}
